//-----------------------------------------------------------------------------
// File: CreditsDevice.cs
//
// Copyright (c) Dmitry Shuklin. All rights reserved.
//-----------------------------------------------------------------------------
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;


namespace ObjectiveDraw.Platform.Information
{
	/// <summary>
	/// Summary description for CreditsDevice.
	/// </summary>
	internal class CreditsDevice : Cerebrum.Direct3D.Forms.DeviceControl
	{
		System.Drawing.Bitmap m_TextureBitmap;

		object m__ImageTexture = new object();
		object m__VertexBuffer = new object();

		internal CreditsDevice()
		{
			//
			// TODO: Add constructor logic here
			//
			string message = FromString("T2JqZWN0aXZlIERyYXcNCg0KQXVndXN0LCAyMDA2IC0gTWF5LCAyMDA4DQoNCg0KDQpjaGllZiBzb2Z0d2FyZSBhcmNoaXRlY3Q6DQpEbWl0cnkgU2h1a2xpbg0KDQoNCg0KcHJvZ3JhbW1pbmc6DQpEbWl0cnkgU2h1a2xpbiwNClNlcmdleSBCb3lrbywNCkFsZXhhbmRlciBDb3p1YmVyZGEsDQpWbGFkaW1pciBMZXNoY2hpbnNreQ0KDQoNCg0K");

			System.Drawing.Font font = new System.Drawing.Font("Verdana", 9);
			System.Drawing.Brush brush = new System.Drawing.SolidBrush(System.Drawing.Color.Yellow);

			System.Drawing.StringFormat format = new System.Drawing.StringFormat();
			format.Alignment = System.Drawing.StringAlignment.Center;

			InitializeComponent();

			m_TextureBitmap = DrawTextToBitmap(message, font, brush, format);
		}

		public static System.Drawing.Bitmap DrawTextToBitmap(string text, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.StringFormat format)
		{
			System.Drawing.Bitmap _bitmap = new System.Drawing.Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
			System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(_bitmap);
			
			System.Drawing.SizeF sizef = g.MeasureString(text, font, 1024, format);
			System.Drawing.Size size = sizef.ToSize();
			size.Width += 2;
			size.Height += 2;

			g.Dispose();
			_bitmap.Dispose();

			_bitmap = new System.Drawing.Bitmap(size.Width, size.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
			g = System.Drawing.Graphics.FromImage(_bitmap);
			g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
			g.DrawString(text, font, brush, new System.Drawing.RectangleF(0, 0, size.Width, size.Height), format);
			g.Dispose();
			return _bitmap;
		}

		private void InitializeComponent()
		{
			// 
			// CreditsDevice
			// 
			this.ForeColor = System.Drawing.Color.Black;

		}

		public static string FromString(string s)
		{
			string r;
			byte [] buff = Convert.FromBase64String(s);
			System.IO.MemoryStream ms = new System.IO.MemoryStream(buff);
			System.IO.StreamReader sr = new System.IO.StreamReader(ms);
			r = sr.ReadToEnd();
			sr.Close();
			ms.Close();
			return r;
		}


		protected override void OnUpdateScene(Cerebrum.Direct3D.Forms.DeviceEventArgs e)
		{

			System.DateTime time = System.DateTime.Now;

			time = new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second);

			base.OnUpdateScene (e);

			// Setup the lights and materials
			SetupLights();
			// Setup the world, view, and projection matrices
			SetupMatrices();
		}
		
		/// <summary>
		/// Called once per frame, the call is the entry point for 3d rendering. This 
		/// function sets up render states, clears the viewport, and renders the scene.
		/// </summary>
		protected override void OnRenderScene(Cerebrum.Direct3D.Forms.RenderEventArgs e)
		{
			//Clear the backbuffer to a black color 
			m_Device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, this.ForeColor, 1.0f, 0);
			
			//Begin the scene
			m_Device.BeginScene();

			base.OnRenderScene (e);

			RectangleF rectangle = new RectangleF(0,0,m_TextureBitmap.Width,m_TextureBitmap.Height);


			Texture _ImageTexture = Cerebrum.Direct3D.Drawing.Graphics.DeviceObjects[e.Device, m__ImageTexture] as Texture;

			if(_ImageTexture == null)
			{
				_ImageTexture = Texture.FromBitmap(e.Device, m_TextureBitmap, 0, Pool.Managed);
				Cerebrum.Direct3D.Drawing.Graphics.DeviceObjects[e.Device, m__ImageTexture] = _ImageTexture;
			}
				
			VertexBuffer _VertexBuffer = Cerebrum.Direct3D.Drawing.Graphics.DeviceObjects[m_Device, m__VertexBuffer] as VertexBuffer;
			if(_VertexBuffer==null)
			{
				_VertexBuffer = new VertexBuffer(typeof(CustomVertex.TransformedColoredTextured), 6, m_Device, Usage.WriteOnly | Usage.Dynamic, 0, Pool.SystemMemory);
				Cerebrum.Direct3D.Drawing.Graphics.DeviceObjects[m_Device, m__VertexBuffer] = _VertexBuffer;

				CustomVertex.TransformedColoredTextured[] fontVertices = new CustomVertex.TransformedColoredTextured[6];

				float xpos;
				float ypos;
				float w;
				float h;

				xpos = rectangle.X;
				ypos = rectangle.Y;
				w = rectangle.Width;
				h = rectangle.Height;

				float tx1 = 0;
				float ty1 = 0;
				float tx2 = 1.0f;
				float ty2 = 1.0f;
				float z = this.m_Z;

				int clr = System.Drawing.Color.Yellow.ToArgb();

				fontVertices[0] = new CustomVertex.TransformedColoredTextured(new Vector4(xpos+0-0.5f,ypos+h-0.5f,z,1.0f), clr, tx1, ty2);
				fontVertices[1] = new CustomVertex.TransformedColoredTextured(new Vector4(xpos+0-0.5f,ypos+0-0.5f,z,1.0f), clr, tx1, ty1);
				fontVertices[2] = new CustomVertex.TransformedColoredTextured(new Vector4(xpos+w-0.5f,ypos+h-0.5f,z,1.0f), clr, tx2, ty2);
				fontVertices[3] = new CustomVertex.TransformedColoredTextured(new Vector4(xpos+w-0.5f,ypos+0-0.5f,z,1.0f), clr, tx2, ty1);
				fontVertices[4] = new CustomVertex.TransformedColoredTextured(new Vector4(xpos+w-0.5f,ypos+h-0.5f,z,1.0f), clr, tx2, ty2);
				fontVertices[5] = new CustomVertex.TransformedColoredTextured(new Vector4(xpos+0-0.5f,ypos+0-0.5f,z,1.0f), clr, tx1, ty1);

				_VertexBuffer.SetData(fontVertices, 0, LockFlags.Discard);
			}


			RenderStateManager renderState = m_Device.RenderState;

			renderState.AlphaBlendEnable = true;
			renderState.SourceBlend = Blend.SourceAlpha;
			renderState.DestinationBlend = Blend.InvSourceAlpha;
			renderState.AlphaTestEnable = true;
			renderState.ReferenceAlpha = 0x08;
			renderState.AlphaFunction = Compare.GreaterEqual;

			TextureStateManager textureState0;

			textureState0 = m_Device.TextureState[0];

			textureState0.ColorOperation = TextureOperation.Modulate;
			textureState0.ColorArgument1 = TextureArgument.TextureColor;
			textureState0.ColorArgument2 = TextureArgument.Diffuse;
			textureState0.AlphaOperation = TextureOperation.Modulate;
			textureState0.AlphaArgument1 = TextureArgument.TextureColor;
			textureState0.AlphaArgument2 = TextureArgument.Diffuse;
			textureState0.TextureCoordinateIndex = 0;
			textureState0.TextureTransform = TextureTransform.Disable; // REVIEW

			m_Device.SetTexture(0, _ImageTexture);
			m_Device.VertexFormat = CustomVertex.TransformedColoredTextured.Format;
			m_Device.PixelShader = null;

			m_Device.SetStreamSource(0, _VertexBuffer, 0);
			m_Device.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);
			m_Device.SetTexture(0, null);

			// End the scene
			m_Device.EndScene();
		}

		
		/// <summary>
		/// Setup the matrices
		/// </summary>
		private void SetupMatrices()
		{
			// move the object
			/*Matrix temp = Matrix.Translation(-(bufferSize*0.6f), 0, 0);//-(bufferSize*0.5f));

			// For our world matrix, we will just rotate the object about the indexY-axis.
			m_Device.Transform.World = Matrix.Multiply(temp, Matrix.RotationAxis(new Vector3(0,
				1.0f,
				0), 
				(Environment.TickCount % 7200) / 3600.0f * (float)Math.PI));*/
			/*temp;*/
			// Set up our view matrix. A view matrix can be defined given an eye point,
			// a point to lookat, and a direction for which way is up. Here, we set the
			// eye five units back along the z-axis and up three units, look at the
			// origin, and define "up" to be in the indexY-direction.
			/*m_Device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 25.0f,-30.0f),
				new Vector3(0.0f, 0.0f, 0.0f), 
				new Vector3(0.0f, 1.0f, 0.0f));*/

			/*m_Device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 0.0f, 10.0f),
				new Vector3(0.0f, 0.0f, 0.0f), 
				new Vector3(0.0f, 1.0f, 0.0f));*/
			// For the projection matrix, we set up a perspective transform (which
			// transforms geometry from 3D view space to 2D viewport space, with
			// a perspective divide making objects smaller in the distance). To build
			// a perpsective transform, we need the field of view (1/4 pi is common),
			// the aspect ratio, and the near and far clipping planes (which define at
			// what distances geometry should be no longer be rendered).
			//m_Device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, 1.0f, 0.0f, 100.0f);
			/*m_Device.Transform.Projection = Matrix.PerspectiveOffCenterLH(-10, 10, -10, 10, -10, 10);*/


		}

        
        
        
        
		/// <summary>
		/// Setup the lights
		/// </summary>
		private void SetupLights()
		{
			Color col = Color.White;
			//Set up a material. The material here just has the diffuse and ambient
			//colors set to yellow. Note that only one material can be used at a time.
			Material mtrl = new Material();
			mtrl.Diffuse = 	mtrl.Ambient = col;
			m_Device.Material = mtrl;
			
			//Set up a white, directional light, with an oscillating direction.
			//Note that many lights may be active at a time (but each one slows down
			//the rendering of our scene). However, here we are just using one. Also,
			//we need to set the D3DRS_LIGHTING renderstate to enable lighting
    
			m_Device.Lights[0].Type = LightType.Directional;
			m_Device.Lights[0].Diffuse = Color.Purple;
			m_Device.Lights[0].Direction = new Vector3(0, 1.0f,	0);

#warning "porting"
			//m_Device.Lights[0].Commit();
			m_Device.Lights[0].Enabled = true;

			//Finally, turn on some ambient light.
			//Ambient light is light that scatters and lights all objects evenly
			m_Device.RenderState.Ambient = Color.Gray;
		}

	}
}
